﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;

namespace SLBehaviourSystem
{
    public class BehaviourConfigUtils
    {
        static string ConfigTemplate;
        static string DefineTemplate;
        static string DictTemplate;

        static string TemplatePath = Application.dataPath + "/Plugins/BehaviourSystem/Editor/Scripts/Template/";
        static string ConfigPath = Application.dataPath + "/Plugins/BehaviourSystem/Scripts/BehaviourNodeConfig.cs";

        public static void CreateNodeConfig()
        {
            if (string.IsNullOrEmpty(ConfigTemplate))
            {
                string path = TemplatePath + "ConfigTemplate.cs";
                ConfigTemplate = File.ReadAllText(path);
                ConfigTemplate = ConfigTemplate.Replace("/*", "").Replace("*/", "");
                path = TemplatePath + "DefineTemplate.cs";
                DefineTemplate = File.ReadAllText(path);
                DefineTemplate = DefineTemplate.Replace("//", "");
                path = TemplatePath + "DictTemplate.cs";
                DictTemplate = File.ReadAllText(path);
                DictTemplate = DictTemplate.Replace("//", "");
            }

            Assembly slBehaviourSystem = Assembly.GetAssembly(typeof(BehaviourSystem));
            Type[] types = slBehaviourSystem.GetTypes();
            List<Type> actionTypes = new List<Type>();
            List<Type> conditionTypes = new List<Type>();
            List<Type> compositeTypes = new List<Type>();
            List<Type> decoratorTypes = new List<Type>();

            for (int i = 0; i < types.Length; i++)
            {

                if (types[i].IsDefined(typeof(ActionNodeAttribute), false))
                {
                    actionTypes.Add(types[i]);
                }

                if (types[i].IsDefined(typeof(ConditionNodeAttribute), false))
                {
                    conditionTypes.Add(types[i]);
                }

                if (types[i].IsDefined(typeof(DecoratorNodeAttribute), false))
                {
                    decoratorTypes.Add(types[i]);
                }

                if (types[i].IsDefined(typeof(CompositeNodeAttribute), false))
                {
                    compositeTypes.Add(types[i]);
                }
            }
            StringBuilder defines = new StringBuilder();
            StringBuilder actionDict = new StringBuilder();
            StringBuilder conditionDict = new StringBuilder();
            StringBuilder compositeDict = new StringBuilder();
            StringBuilder decoratorDict = new StringBuilder();

            defines.Append("\n//Action\n");
            for (int i = 0; i < actionTypes.Count; i++)
            {
                string name = actionTypes[i].Name.Replace("Node", "");
                defines.Append(DefineTemplate.Replace("{Name}", name));

                actionDict.Append(DictTemplate.Replace("{Name}", name));
            }

            defines.Append("\n//Condition\n");
            for (int i = 0; i < conditionTypes.Count; i++)
            {
                string name = conditionTypes[i].Name.Replace("Node", "");
                defines.Append(DefineTemplate.Replace("{Name}", name));

                conditionDict.Append(DictTemplate.Replace("{Name}", name));
            }

            defines.Append("\n//Composite\n");
            for (int i = 0; i < compositeTypes.Count; i++)
            {
                string name = compositeTypes[i].Name.Replace("Node", "");
                defines.Append(DefineTemplate.Replace("{Name}", name));

                compositeDict.Append(DictTemplate.Replace("{Name}", name));
            }

            defines.Append("\n//Decorator\n");
            for (int i = 0; i < decoratorTypes.Count; i++)
            {
                string name = decoratorTypes[i].Name.Replace("Node", "");
                defines.Append(DefineTemplate.Replace("{Name}", name));

                decoratorDict.Append(DictTemplate.Replace("{Name}", name));
            }

            string final = ConfigTemplate.Replace("{Defines}", defines.ToString());
            final = final.Replace("{ActionDict}", actionDict.ToString());
            final = final.Replace("{ConditionDict}", conditionDict.ToString());
            final = final.Replace("{CompositeDict}", compositeDict.ToString());
            final = final.Replace("{DecoratorDict}", decoratorDict.ToString());

            File.WriteAllText(ConfigPath, final);
            DebugUtils.Log(final);
        }


        static string ComponentConfigTemplate;
        static string ComponentDefineTemplate;
        static string ComponentDictTemplate;

        static string ComponentTemplatePath = Application.dataPath + "/Plugins/BehaviourSystem/Editor/Scripts/Template/";
        static string ComponentConfigPath = Application.dataPath + "/Plugins/BehaviourSystem/Scripts/BehaviourComponentConfig.cs";
        public static void CreateComponentConfig()
        {
            if (string.IsNullOrEmpty(ConfigTemplate))
            {
                string path = TemplatePath + "ComponentConfigTemplate.cs";
                ConfigTemplate = File.ReadAllText(path);
                ConfigTemplate = ConfigTemplate.Replace("/*", "").Replace("*/", "");
                path = TemplatePath + "DefineTemplate.cs";
                DefineTemplate = File.ReadAllText(path);
                DefineTemplate = DefineTemplate.Replace("//", "");
                path = TemplatePath + "ComponentDictTemplate.cs";
                DictTemplate = File.ReadAllText(path);
                DictTemplate = DictTemplate.Replace("//", "");
            }

            Assembly slBehaviourSystem = Assembly.GetAssembly(typeof(BehaviourSystem));
            Type[] types = slBehaviourSystem.GetTypes();
            List<Type> actionTypes = new List<Type>();
            List<Type> conditionTypes = new List<Type>();

            for (int i = 0; i < types.Length; i++)
            {
                
                if (types[i].IsDefined(typeof(ActionComponentAttribute), false))
                {
                    actionTypes.Add(types[i]);
                }

                if (types[i].IsDefined(typeof(ConditionComponentAttribute), false))
                {
                    conditionTypes.Add(types[i]);
                }
            }
            StringBuilder defines = new StringBuilder();
            StringBuilder actionDict = new StringBuilder();
            StringBuilder conditionDict = new StringBuilder();

            defines.Append("\n//Action\n");
            for (int i = 0; i < actionTypes.Count; i++)
            {
                string name = actionTypes[i].Name.Replace("Component", "");
                defines.Append(DefineTemplate.Replace("{Name}", name));

                actionDict.Append(DictTemplate.Replace("{Name}", name));
            }

            defines.Append("\n//Condition\n");
            for (int i = 0; i < conditionTypes.Count; i++)
            {
                string name = conditionTypes[i].Name.Replace("Component", "");
                defines.Append(DefineTemplate.Replace("{Name}", name));

                conditionDict.Append(DictTemplate.Replace("{Name}", name));
            }

            string final = ConfigTemplate.Replace("{Defines}", defines.ToString());
            final = final.Replace("{ActionDict}", actionDict.ToString());
            final = final.Replace("{ConditionDict}", conditionDict.ToString());

            File.WriteAllText(ComponentConfigPath, final);
            DebugUtils.Log(final);
        }
    }
}
